package com.example.framwork.exception;

import com.example.framwork.code.CodeConst;
import com.example.framwork.result.ProjectResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author Sheeper
 * @date 2018/5/17.
 */
@RestControllerAdvice
public class ExceptionHandlers {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ProjectResult handHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        return new ProjectResult(CodeConst.NOT_SUPPORT, e.getMessage());
    }

    @ExceptionHandler(ValidateException.class)
    public ProjectResult handValidateException(ValidateException e) {
        logger.error(e.getMsg(), e);
        if (StringUtils.isEmpty(e.getMsg())) {
            return new ProjectResult(CodeConst.PARAM_ERROR, ("request_param_error"));
        }
        return new ProjectResult(CodeConst.PARAM_ERROR, e.getMsg());
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ProjectResult handHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        logger.error(e.getMessage(), e);
        return new ProjectResult(CodeConst.PARAM_ERROR, ("request_param_error"));
    }

    @ExceptionHandler(UniqueException.class)
    public ProjectResult handUniqueException(UniqueException e) {
        logger.error(e.getMessage(), e);
        String msg = (e.getMessage());
        return new ProjectResult(CodeConst.PARAM_ERROR, msg);
    }
    @ExceptionHandler(AccessDeniedException.class)
    public ProjectResult handleAccessDeniedException(AccessDeniedException e) {
        return new  ProjectResult(CodeConst.NO_PERMISSION, "无权限访问");
    }


    @ExceptionHandler(NumberFormatException.class)
    public ProjectResult handleNumberFormatException(NumberFormatException e) {
        logger.error(e.getMessage());
        return new ProjectResult(CodeConst.PARAM_ERROR, ("request_param_error"));
    }

    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public ProjectResult handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        logger.error(e.getMessage(), e);
        return new ProjectResult(CodeConst.PARAM_ERROR, ("request_param_error"));
    }

    @ExceptionHandler(UnifoundIcException.class)
    public ProjectResult handleFileTypeException(UnifoundIcException e) {
        logger.error(e.getMessage(), e);
        String msg = (e.getMessage());
        int code = (e.getCode() == null ? CodeConst.FAILED : e.getCode());
        return new ProjectResult(code, msg);
    }

    @ExceptionHandler(PadException.class)
    public Map<String, Object> handlePadException(PadException e) {
        logger.error(e.getMessage(), e);
        String msg = e.getMessage();
        Map<String, Object> resultMap = new HashMap<>();
        if (e.getCode() != null) {
            resultMap.put("code", e.getCode());
        } else {
            resultMap.put("code", CodeConst.FAILED);
        }
        resultMap.put("szErrorInfo", msg);
        return resultMap;
    }

    /**
     * #@RequestBody 请求时抛出的错误
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ProjectResult handException(ConstraintViolationException e) {
        String msg = null;
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        if (!CollectionUtils.isEmpty(constraintViolations)) {
            msg = constraintViolations.iterator().next().getMessage();
        }

        return new ProjectResult(CodeConst.PARAM_ERROR, msg);
    }

    /**
     * #@RequestBody和@Validated共同作用时抛出的错误
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ProjectResult handException(MethodArgumentNotValidException e) {
        String msg = null;
        BindingResult bindingResult = e.getBindingResult();
        if (bindingResult.hasErrors()) {
            msg = bindingResult.getFieldError().getDefaultMessage();
        }
        msg = ("request_param_error");
        return new ProjectResult(CodeConst.PARAM_ERROR, msg);
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ProjectResult handException(MissingServletRequestParameterException e) {

        logger.error(e.getMessage());
        String msg = ("request_params_miss");
        return new ProjectResult(CodeConst.FAILED, msg);
    }

    /**
     * #@Valid和@Validated 验证后抛出的错误
     *
     * @param e
     * @return
     */
    @ExceptionHandler(BindException.class)
    public ProjectResult handBindException(BindException e) {
        logger.error(e.getMessage());
        String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        String msg = (message);
        return new ProjectResult(CodeConst.FAILED, msg);
    }

    @ExceptionHandler(BusinessLogicException.class)
    public ProjectResult handleFileTypeException(BusinessLogicException e) {
        String msg = e.getMessage();
        logger.error("消息：" + e.getMessage() + ", 中文：" + msg);
        int code = (e.getCode() == null ? CodeConst.FAILED : e.getCode());
        return new ProjectResult(code, msg);
    }

    @ExceptionHandler(Exception.class)
    public ProjectResult handException(Exception e) {
        logger.error(e.getMessage(), e);
        String msg = ("com_system_error");
        return new ProjectResult(CodeConst.INTERNAL_ERROR, msg);
    }
}


